import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.SplashScreen;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
* @file EventHandler.java
*
* @brief Diese Datei enthält die EventHandler-Klasse.
*
* @author Alrik Künne
*
* @date 01.06.2012 - erste Version
* @date 19.06.2012 - einige Veränderungen, Multi-Threading
**/

/** 
* @class EventHandler 
* 
* @brief die Klasse kümmert sich um die Ereignisse der GUI
* 
* Der Eventhandler erzeugt die Fenster, wartet auf die Events und erstellt entsprechende Objekte 
* 
*/ 
public class EventHandler{
	SimuFrame viewHouse;
	PopupFrame viewPopup;
	Lift lift;
	Trigger trigger;
	
	/**
	*@brief Konstruktor
	* 
	* es werden die Fenster erzeugt und die ActionListener an die Oberflächenelemente gebunden
	*/
	public EventHandler(){
		lift = new Lift();//* Model
		viewHouse = new SimuFrame("LiftSimu " + "v0.9.2");//* View erzeugen und öffnen
		viewPopup = new PopupFrame(); //* View erzeugen aber nicht öffnen
		allocHandleEvents();
		

		trigger= new Trigger(lift, viewHouse);
		trigger.start();
		
		closeSplash(); //* Beendet den Splashscreen
	}
	
	/** 
	* @brief Weist allen GUI-Elementen ihr HandleEvent zu
	* 
	* damit was passiert hat jedes Element ein HandleEvent, diese werden hier vereinbart
	*/ 
	private void allocHandleEvents(){
		for(int i=0; i<9; i++){
			//Zuweisung für die Ruftasten
			if(i<8)
			viewHouse.levelpanels[i].Down.addActionListener(new HandleCallBPressed() );
			if(i>0)
			viewHouse.levelpanels[i].Up.addActionListener(new HandleCallBPressed() );
			//Zuweisung für die Auswahltasten
			viewHouse.liftpanel.buttons[i].addActionListener(new HandleChooseBPressed() );
		}
		//Zuweisung des Okay-Buttons
		viewPopup.bPopupOK.addActionListener(new HandleOKBPressed());
		viewPopup.bPopupCancel.addActionListener(new HandleCancelBPressed());
		//Zuweisung des Spinner zu seinem Event
		viewPopup.sAnzahl.addChangeListener(new SpinnerListener());
		viewHouse.liftpanel.Doorsclose.addActionListener(new HandleDoorsCloseBPressed());
		viewHouse.liftpanel.Doorsopen.addActionListener(new HandleDoorsOpenBPressed());
		viewPopup.addWindowListener(new HandlePopupClose());
	}

	/**
	 * @brief schließt das evtl. vorhandene Splashfenster beim Programmstart
	 * 
	 * Quelle: http://docs.oracle.com/javase/tutorial/uiswing/misc/splashscreen.html
	 */
	private void closeSplash(){
		final SplashScreen splash = SplashScreen.getSplashScreen();
		if (splash == null) {
			System.out.println("SplashScreen.getSplashScreen() returned null");
			return;
		}
		Graphics2D g = splash.createGraphics();
		if (g == null) {
			System.out.println("g is null");
			return;
		}
	}
	
	/** 
	* @class HandleCallBPressed 
	* 
	* @brief erstellt das HandleEvent für  die CallButtons
	* 
	*/ 
	class HandleCallBPressed implements ActionListener{
		
		/**
		 *@brief die Aktion, die beim Drücken der Ruftaste ausgeführt wird
		 *
		 * Wenn ein Ruf-Knopf gedrückt wurde, dann wird festgestellt, auf welcher Etage und in<br/>
		 * welcher Etage. Wenn der Fahrtwunsch festgestellt wurde, so wird das der Klasse Lift mit der Methode setFahrtwunsch(int) gemeldet.<br/>
		 */
		public void actionPerformed(ActionEvent evt){
			int Fahrtwunsch=1;
			System.out.println("eine Ruftaste wurde gedrückt");
			JButton pressed = (JButton)evt.getSource();
			pressed.setBackground(Color.RED);
			//Feststellen welche Taste gedrückt wurde
			for(int i=1; i<9; i++){
				if (viewHouse.levelpanels[i-1].Down==pressed){
					Fahrtwunsch=-(10-i);
					break;
				}else{
					if (viewHouse.levelpanels[i-1].Up==pressed){
						Fahrtwunsch=10-i;
						break;
					}
				}
			}
			//der Liftanalage den Fahrtwunsch mitteilen
			if(!lift.setFahrtwunsch(Fahrtwunsch))
				pressed.setBackground(Color.white);
		}
	}
	
	/** 
	* @class HandleChooseBPressed 
	* 
	* @brief erstellt das HandleEvent für die ChooseButtons
	* 
	*/ 
	class HandleChooseBPressed implements ActionListener{
		
		/**
		 *@brief die Aktion, die beim Drücken der Wahltaste ausgeführt wird
		 *
		 * Wenn eine Wahlttaste gedrückt wurde, wird hier festgestellt, welcht Taste das war.<br/>
		 * anschließend wird das PopupFrame angezeigt, wenn der Lift nicht fährt. das Hauptfenster wird pausiert.
		 */
		public void actionPerformed(ActionEvent evt){
			
			System.out.println("eine Wahltaste wurde gedrückt");
			JButton pressed = (JButton)evt.getSource();
			if(lift.getdoorcond()>0 && lift.doorcloseAction==null && lift.overloadAction==null){ //TODO könnte besser gemacht werden
				int Etage=Integer.parseInt(pressed.getText());  //nicht gerade besonders hübsch
				if(Etage!=lift.getetage()){
					lift.settimeinterruptflag(true);
					viewPopup.setEtage(Etage);
					viewHouse.setEnabled(false);
					viewPopup.setVisible(true);
				}
			}
		}
	}
	
	/** 
	* @class HandleOKBPressed 
	* 
	* @brief erstellt das HandleEvent für  den OK-Button
	*
	*/ 
	class HandleOKBPressed implements ActionListener{
		
		/**
		 *@brief die Aktion, die beim Drücken des OK-Buttons des PopupFrame ausgeführt wird 
		 *
		 * Wenn auf dem PopupFrame "OK" gedrückt wurde, so schließt sich das PopupFrame und die Personen werden in Lift verbucht.<br/>
		 * Falls es eine Überlast gibt, wird diese hier eingeleitet. Wenn die Personen keine Überlast erzeugen, so wird läuft die Simulation weiter.
		 */
		public void actionPerformed(ActionEvent evt){
			System.out.println("Der OK-Button wurde gedrückt");
			viewHouse.setEnabled(true);
			viewPopup.setVisible(false);
			//Fenster wieder aktiv
			int Carry=lift.addPeopleandreturnCarry(viewPopup.getEtage(), viewPopup.getAnz());
			if(Carry!=0){
				//Überlastroutine einleiten
				System.out.println("****ÜBERLAST*****");
				lift.startoverloadroutine(Carry);
				//viewHouse.toFront();
				//viewPopup.setVisible(false);
			}else{
				//keine Überlast
				
				viewHouse.liftpanel.buttons[viewPopup.getEtage()-1].setBackground(Color.RED);
				lift.settimeinterruptflag(false);
			}
		}
	}
	
	/** 
	* @class HandleCancelBPressed 
	* 
	* @brief erstellt das HandleEvent für den Abbrechen-Button auf dem PopupFrame.
	* 
	*/ 
	class HandleCancelBPressed implements ActionListener{
		
		/**
		 *@brief die Aktion, die beim Drücken des Cancel-Buttons des PopupFrame ausgeführt wird 
		 *
		 * Das PopupFrame wird geschlossen und das Hauptfenster wird wieder angezeigt-die Simulation kehrt in den vorherigen Zustand zurück.
		 */
		public void actionPerformed(ActionEvent evt){
			System.out.println("Der Cancel-Button wurde gedrückt");
			viewHouse.setEnabled(true);
			viewPopup.setVisible(false);
			lift.settimeinterruptflag(false);
		}
	}	
	
	/** 
	* @class HandlePopupClose 
	* 
	* @brief reagiert auf das schließen des PopupFrame über die OS-Funktion
	* 
	*/ 
	class HandlePopupClose implements WindowListener{
		
		/**
		 *@brief die Aktion, die beim Drücken des Schließbuttons-Buttons des PopupFrame ausgeführt wird 
		 *
		 * Das PopupFrame wird geschlossen und das SimuFrame wird wieder angezeigt
		 */
		 public void windowClosing(WindowEvent we){
			 viewHouse.setEnabled(true);
			 viewPopup.setVisible(false);
			 lift.settimeinterruptflag(false);
		 }

		//Folgende Funktionen müssen aufgelistet werden, es findet aber keine Aktion statt
		//Diese Funktionen müssen wir auflisten, damit wir das schließen-Event abfangen können. 
		@Override
		public void windowActivated(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void windowClosed(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void windowDeactivated(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void windowDeiconified(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void windowIconified(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void windowOpened(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}
	}
	
	
	/** 
	* @class HandleDoorsCloseBPressed 
	* 
	* @brief erstellt das HandleEvent für  die Tür-Schließen-Buttons
	* 
	*/ 
	class HandleDoorsCloseBPressed implements ActionListener{
		
		/**
		 *@brief die Aktion, die beim Drücken des Türen-Schließen-Buttons ausgeführt wird
		 *
		 * Wenn auf den Schließen-Button in der Liftkabine (JLiftPanel) gedrückt wird, so wird geprüft ob eine Person im Lift ist.<br/>
		 * Wenn min. eine Person in der Kabine ist, dann wird die Tür geschlossen, ansonsten wird keine Aktion ausgeführt.
		 * In der Klasse Lift wird die Methode closeDoors() gerufen.
		 */
		public void actionPerformed(ActionEvent evt){
			if(lift.getAllPeople()!=0) //Die Türen werden nur geschlossen, wenn eine Person im Fahrstuhl ist.
				lift.closeDoors();	
			System.out.println("Der Türschließ-Button wurde gedrückt");
		}
	}
	
	/** 
	* @class HandleDoorsOpenBPressed 
	* 
	* @brief erstellt das HandleEvent für die Tür-Öffnen-Buttons
	*
	* Wenn auf den Öffnen-Button in der Liftkabine (JLiftPanel) gedrückt wird, so wird geprüft ob eine Person im Lift ist.<br/>
	* Wenn min. eine Person in der Kabine ist und die Kabine nicht fährt, dann wird die Tür geöffnet, ansonsten wird keine Aktion ausgeführt.
	* In der Klasse Lift wird die Methode openDoors() gerufen.
	*/ 
	class HandleDoorsOpenBPressed implements ActionListener{
		
		/**
		 *@brief die Aktion, die beim Drücken des Türen-Öffnen-Buttons ausgeführt wird
		 *
		 * 
		 */
		public void actionPerformed(ActionEvent evt){
			System.out.println("Der Türöffnen-Button wurde gedrückt");
			if(lift.getAllPeople()!=0)
				lift.openDoors();
		}
	}
	
	
	/** 
	* @class SpinnerListener 
	* 
	* @brief erstellt das HandleEvent für den ChangeListener
	* 
	* Wenn die Personen im PopupFrame ausgewählt werden ist, lauscht der SpinnerListener
	*/ 
	class SpinnerListener implements ChangeListener {
		
		/**
		 *@brief die Aktion, die beim Ändern des Spinners ausgeführt wird
		 *
		 * momentan ohne Funktion, aber vielleicht brauchen wir es nochmal
		 */
	    public void stateChanged(ChangeEvent evt) {
	        System.out.println("Der Spinner wurde geändert");
	        
	    }
	}
}
